//
// Created by A4-28 on 2020/10/15.
//
#include <entt/entt.hpp>
#include "scene.h"

namespace WF {
    class Entity {

    public:
        Entity(entt::entity obj, Scene *scene) : scene(scene), gameObj(obj) {

        }

        ~Entity() {}

        template<typename T, typename ...Args>
        T &AddComponent(Args &&...args) {
            return scene->GetRegistry().emplace<T>(gameObj, std::forward<Args>(args)...);
        }

        template<typename T, typename ...Args>
        T &GetComponent(Args &&...args) {
            return scene->GetRegistry().get<T>(gameObj, std::forward<Args>(args)...);
        }

        template<typename T, typename ...Args>
        T &RemoveComponent(Args &&...args) {
            return scene->GetRegistry().remove<T>(gameObj, std::forward<Args>(args)...);
        }

        template<typename T>
        T *TryGetComponent() {
            return scene->GetRegistry().try_get<T>(gameObj);
        }

        template<typename T>
        bool HasComponent() {
            return scene->GetRegistry().has<T>(gameObj);
        }

        template<typename T, typename... Args>
        T &GetOrAddComponent(Args &&... args) {
            return scene->GetRegistry().get_or_emplace<T>(gameObj, std::forward<Args>(args)...);
        }

        template<typename T, typename... Args>
        void AddOrReplaceComponent(Args &&... args) {
            scene->GetRegistry().emplace_or_replace<T>(gameObj, std::forward<Args>(args)...);
        }

        void SetParent(Entity entity);

        Entity GetParent();

        void SetActive(bool isActive) { active = isActive; }

        bool isActive() { return active; }

    private:
        entt::entity gameObj = entt::null;
        Scene *scene;
        bool active = true;
        std::string tag;
    };
}
